//
// Created by Bennetty74 on 2021.3.30.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "../header/runner.h"
#include "../header/com_bennetty74_runner_Runner.h"

JNIEXPORT void JNICALL Java_com_bennetty74_runner_Runner_run
(JNIEnv * jniEnv, jobject jobject1, jobject jobject2, jobject jobject3){

    //获取对象的class
    jclass runConfig = (*jniEnv)->GetObjectClass(jniEnv,jobject2);

    //获取maxCpuTime属性
    jfieldID maxCpuTimeField = (*jniEnv) -> GetFieldID(jniEnv,runConfig,"maxCpuTime","I");
    //获取maxCpuTime属性值
    jint maxCpuTime = (*jniEnv)->GetIntField(jniEnv,jobject2,maxCpuTimeField);
//    printf("Max Cpu Time is %ld\n",maxCpuTime);

    //获取maxRealTime属性
    jfieldID maxRealTimeField = (*jniEnv) -> GetFieldID(jniEnv,runConfig,"maxRealTime","I");
    //获取maxRealTime属性值
    jint maxRealTime = (*jniEnv)->GetIntField(jniEnv,jobject2,maxRealTimeField);
//    printf("Max Real Time is %ld\n",maxRealTime);

    //获取maxMemory属性
    jfieldID maxMemoryField = (*jniEnv) -> GetFieldID(jniEnv,runConfig,"maxMemory","J");
    //获取maxMemory属性值
    jlong maxMemory = (*jniEnv)->GetLongField(jniEnv,jobject2,maxMemoryField);
//    printf("Max Memory is %ld\n",maxMemory);

    //获取maxProcessNumber属性
    jfieldID maxProcessNumberField = (*jniEnv) -> GetFieldID(jniEnv,runConfig,"maxProcessNumber","I");
    //获取maxProcessNumber属性值
    jint maxProcessNumber = (*jniEnv)->GetIntField(jniEnv,jobject2,maxProcessNumberField);
//    printf("Max Process Number is %ld\n",maxProcessNumber);

    //获取maxOutputSize属性
    jfieldID maxOutputSizeField = (*jniEnv) -> GetFieldID(jniEnv,runConfig,"maxOutputSize","J");
    //获取maxOutputSize属性值
    jlong maxOutputSize = (*jniEnv)->GetLongField(jniEnv,jobject2,maxOutputSizeField);
//    printf("Max Output Size is %ld\n",maxOutputSize);

    //获取maxStackSize属性
    jfieldID maxStackSizeField = (*jniEnv) -> GetFieldID(jniEnv,runConfig,"maxStackSize","J");
    //获取maxStackSize属性值
    jlong maxStackSize = (*jniEnv)->GetLongField(jniEnv,jobject2,maxStackSizeField);
//    printf("Max Stack Size is %ld\n",maxStackSize);

    //获取exePath属性
    jfieldID exePathField = (*jniEnv)->GetFieldID(jniEnv,runConfig,"exePath","Ljava/lang/String;");
    //获取exePath属性值
    jstring jExePath= (jstring) (jstring *) (*jniEnv)->GetObjectField(jniEnv, jobject2, exePathField);
    const char *exePath = (*jniEnv)->GetStringUTFChars(jniEnv,jExePath,NULL);
//    printf("Exe Path is %s\n",exePath);

    //获取exePath属性
    jfieldID inputPathField = (*jniEnv)->GetFieldID(jniEnv,runConfig,"inputPath","Ljava/lang/String;");
    //获取inputPath属性值
    jstring jInputPath= (jstring) (jstring *) (*jniEnv)->GetObjectField(jniEnv, jobject2, inputPathField);
    const char *inputPath = NULL;
    if(jInputPath!=NULL){
        inputPath = (*jniEnv)->GetStringUTFChars(jniEnv,jInputPath,NULL);
    }

    //获取outputPath属性
    jfieldID outputPathField = (*jniEnv)->GetFieldID(jniEnv,runConfig,"outputPath","Ljava/lang/String;");
    //获取outputPath属性值
    jstring jOutputPath= (jstring) (jstring *) (*jniEnv)->GetObjectField(jniEnv, jobject2, outputPathField);
    const char *outputPath = NULL;
    if(jOutputPath!=NULL){
        outputPath = (*jniEnv)->GetStringUTFChars(jniEnv,jOutputPath,NULL);
    }

    //获取errorPath属性
    jfieldID errorPathField = (*jniEnv)->GetFieldID(jniEnv,runConfig,"errorPath","Ljava/lang/String;");
    jstring jErrorPath= (jstring) (jstring *) (*jniEnv)->GetObjectField(jniEnv, jobject2, errorPathField);
    const char *errorPath = NULL;
    if(jErrorPath!=NULL){
        errorPath = (*jniEnv)->GetStringUTFChars(jniEnv,jErrorPath,NULL);
    }

    //获取logPath属性
    jfieldID logPathField = (*jniEnv)->GetFieldID(jniEnv,runConfig,"logPath","Ljava/lang/String;");
    jstring jLogPath= (jstring) (jstring *) (*jniEnv)->GetObjectField(jniEnv, jobject2, logPathField);
    const char *logPath = (*jniEnv)->GetStringUTFChars(jniEnv,jLogPath,NULL);


    //获取seccompRuleName属性
    jfieldID seccompRuleNameField = (*jniEnv)->GetFieldID(jniEnv,runConfig,"seccompRuleName","Ljava/lang/String;");
    jstring jSeccompRuleName= (jstring) (jstring *) (*jniEnv)->GetObjectField(jniEnv, jobject2, seccompRuleNameField);
    const char *seccompRuleName = NULL;
    if(jSeccompRuleName!=NULL){
        seccompRuleName = (*jniEnv)->GetStringUTFChars(jniEnv,jSeccompRuleName,NULL);
    }

    //获取gid属性
    jfieldID gidField = (*jniEnv) -> GetFieldID(jniEnv,runConfig,"gid","I");
    jint gid = (*jniEnv)->GetIntField(jniEnv,jobject2,gidField);


    //获取uid属性
    jfieldID uidField = (*jniEnv) -> GetFieldID(jniEnv,runConfig,"uid","I");
    jint uid = (*jniEnv)->GetIntField(jniEnv,jobject2,uidField);




    struct config _config;
    _config.max_cpu_time = maxCpuTime;
    _config.max_real_time =maxRealTime;
    _config.max_memory = maxMemory;
    _config.max_process_number = maxProcessNumber;
    _config.max_output_size = maxOutputSize;
    _config.max_stack = maxStackSize;

    _config.exe_path = exePath;
    _config.input_path = inputPath;
    _config.output_path = outputPath;
    _config.error_path = errorPath;
    _config.log_path = logPath;
    _config.seccomp_rule_name = seccompRuleName;

    _config.gid = gid;
    _config.uid = uid;

    //todo 参数args和环境env待处理
    //获取env属性
    jfieldID envField = (*jniEnv)->GetFieldID(jniEnv,runConfig,"env","[Ljava/lang/String;");
    //获取env属性值
    jobject jEnvArray =(*jniEnv)->GetObjectField(jniEnv, jobject2, envField);
    //获取数组元素
    int envSize = (*jniEnv)->GetArrayLength(jniEnv, (jobjectArray)jEnvArray);
    for(int i=0;i<envSize;i++){
        jstring envItem =(*jniEnv)->GetObjectArrayElement(jniEnv, jEnvArray, i);
        const char *envItemString = (*jniEnv)->GetStringUTFChars(jniEnv, envItem, NULL);
        _config.env[i] = (char *) malloc(1024 * sizeof(char));
        strcpy(_config.env[i], envItemString);
//        printf("---环境变量：%s---\n", _config.env[i]);
    }
    //必须以NULL结尾
    _config.env[envSize] = NULL;

//    获取args属性
    jfieldID argsField = (*jniEnv)->GetFieldID(jniEnv,runConfig,"args","[Ljava/lang/String;");
//    获取args属性值
    jobjectArray jArgsArray = (*jniEnv)->GetObjectField(jniEnv, jobject2, argsField);
    if(jArgsArray!=NULL){
        //    获取数组元素
        int argsSize = (*jniEnv)->GetArrayLength(jniEnv, jArgsArray);
        char *args[argsSize+1];
        for(int i=0;i<argsSize;i++){
            jstring argsItem =(*jniEnv)->GetObjectArrayElement(jniEnv, jArgsArray, i);
            const char *argsItemString = (*jniEnv)->GetStringUTFChars(jniEnv, argsItem, NULL);
            args[i] = (char *) malloc(1024 * sizeof(char));
            strcpy(args[i], argsItemString);
        }
        //必须以NULL结尾
        args[argsSize] = NULL;
        memcpy(_config.args, args, sizeof(char *) * (argsSize + 1));
//        for(int i=0;i<=argsSize;i++){
//            printf("参数数组元素：%s\n", _config.args[i]);
//        }
    }else{
        //必须以NULL结尾
        _config.args[0] = NULL;
    }



    struct result _result = {0, 0, 0, 0, 0, 0, 0};

    run(&_config,&_result);




    //-------------------------将返回值赋值给java object-----------------------------------
    //获取对象的class
    jclass runResult = (*jniEnv)->GetObjectClass(jniEnv,jobject3);

    //获取cpuTime属性并赋值
    jfieldID cpuTimeField = (*jniEnv)->GetFieldID(jniEnv,runResult,"cpuTime","I");
    (*jniEnv)->SetIntField(jniEnv, jobject3, cpuTimeField, _result.cpu_time);


    //获取realTime属性并赋值
    jfieldID realTimeField = (*jniEnv)->GetFieldID(jniEnv,runResult,"realTime","I");
    (*jniEnv)->SetIntField(jniEnv, jobject3, realTimeField, _result.real_time);


    //获取memory属性并赋值
    jfieldID memoryField = (*jniEnv)->GetFieldID(jniEnv,runResult,"memory","J");
    (*jniEnv)->SetLongField(jniEnv, jobject3, memoryField, _result.memory);

    //获取signal属性并赋值
    jfieldID signalField = (*jniEnv)->GetFieldID(jniEnv,runResult,"signal","I");
    (*jniEnv)->SetIntField(jniEnv, jobject3, signalField, _result.signal);

    //获取exitCode属性并赋值
    jfieldID exitCodeField = (*jniEnv)->GetFieldID(jniEnv,runResult,"exitCode","I");
    (*jniEnv)->SetIntField(jniEnv, jobject3, exitCodeField, _result.exit_code);

    //获取error属性并赋值
    jfieldID errorField = (*jniEnv)->GetFieldID(jniEnv,runResult,"error","I");
    (*jniEnv)->SetIntField(jniEnv, jobject3, errorField, _result.error);

    //获取result属性并赋值
    jfieldID resultField = (*jniEnv)->GetFieldID(jniEnv,runResult,"result","I");
    (*jniEnv)->SetIntField(jniEnv, jobject3, resultField, _result.result);

//    //获取result属性并赋值
//    jfieldID msgField = (*jniEnv)->GetFieldID(jniEnv,runResult,"msg","Ljava/lang/String;");
//    (*jniEnv)->SetObjectField(jniEnv, jobject3, msgField, (jobject) "错误信息");

}
